import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

public class ResourceOccupier {
    // 默认资源占用百分比
    private static final int DEFAULT_CPU_PERCENTAGE = 50;
    private static final int DEFAULT_MEMORY_PERCENTAGE = 50;

    // 实际要占用的资源
    private static int cpuCoresToUse;
    private static long memoryToUseBytes;

    // 系统总资源
    private static int totalCpuCores;
    private static long totalMemoryBytes;

    // 程序运行状态标志
    private static volatile boolean running = true;

    // 保存CPU任务引用，用于停止
    private static CpuIntensiveTask[] cpuTasks;

    public static void main(String[] args) {
        System.out.println("资源占用程序启动...");

        // 获取系统总资源信息
        getSystemResources();

        // 从配置文件读取百分比配置
        loadConfig();

        // 计算要占用的资源
        calculateResourcesToUse();

        System.out.println("系统总资源: " + totalCpuCores + " 核CPU, " +
                formatMemory(totalMemoryBytes));
        System.out.println("目标: 占用 " +
                (cpuCoresToUse * 100.0 / totalCpuCores) + "% CPU (" + cpuCoresToUse + " 核), " +
                (memoryToUseBytes * 100.0 / totalMemoryBytes) + "% 内存 (" + formatMemory(memoryToUseBytes) + ")");

        // 占用内存
        allocateMemory();

        // 创建线程占用CPU
        createCpuThreads();

        // 注册关闭钩子，优雅退出
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            running = false;
            if (cpuTasks != null) {
                for (CpuIntensiveTask task : cpuTasks) {
                    if (task != null) {
                        task.stop();
                    }
                }
            }
            System.out.println("\n程序正在退出...");
        }));

        // 主线程保持运行
        keepRunning();
    }

    /**
     * 获取系统总资源信息
     */
    private static void getSystemResources() {
        // 获取CPU核心数
        totalCpuCores = Runtime.getRuntime().availableProcessors();

        // 获取总内存
        OperatingSystemMXBean osBean = ManagementFactory.getPlatformMXBean(
                com.sun.management.OperatingSystemMXBean.class);
        totalMemoryBytes = osBean.getTotalPhysicalMemorySize();
    }

    /**
     * 从配置文件加载资源占用百分比
     */
    private static void loadConfig() {
        Properties prop = new Properties();
        int cpuPercentage = DEFAULT_CPU_PERCENTAGE;
        int memoryPercentage = DEFAULT_MEMORY_PERCENTAGE;

        try (FileInputStream fis = new FileInputStream("resource_config.properties")) {
            prop.load(fis);

            // 读取CPU百分比配置
            String cpuProp = prop.getProperty("cpu.percentage");
            if (cpuProp != null) {
                cpuPercentage = Integer.parseInt(cpuProp);
                if (cpuPercentage < 0 || cpuPercentage > 100) {
                    System.out.println("CPU百分比配置无效，使用默认值: " + DEFAULT_CPU_PERCENTAGE + "%");
                    cpuPercentage = DEFAULT_CPU_PERCENTAGE;
                }
            }

            // 读取内存百分比配置
            String memoryProp = prop.getProperty("memory.percentage");
            if (memoryProp != null) {
                memoryPercentage = Integer.parseInt(memoryProp);
                if (memoryPercentage < 0 || memoryPercentage > 100) {
                    System.out.println("内存百分比配置无效，使用默认值: " + DEFAULT_MEMORY_PERCENTAGE + "%");
                    memoryPercentage = DEFAULT_MEMORY_PERCENTAGE;
                }
            }

            System.out.println("已加载配置: CPU=" + cpuPercentage + "%, 内存=" + memoryPercentage + "%");
        } catch (IOException e) {
            System.out.println("配置文件未找到或读取失败，使用默认配置: CPU=" +
                    DEFAULT_CPU_PERCENTAGE + "%, 内存=" + DEFAULT_MEMORY_PERCENTAGE + "%");
        } catch (NumberFormatException e) {
            System.out.println("配置文件格式错误，使用默认配置: CPU=" +
                    DEFAULT_CPU_PERCENTAGE + "%, 内存=" + DEFAULT_MEMORY_PERCENTAGE + "%");
        }

        // 计算要使用的CPU核心数和内存大小
        cpuCoresToUse = Math.max(1, (int) (totalCpuCores * cpuPercentage / 100.0));
        memoryToUseBytes = (long) (totalMemoryBytes * memoryPercentage / 100.0);

        // 确保内存不会超过JVM最大可用内存
        long maxJvmMemory = Runtime.getRuntime().maxMemory();
        if (memoryToUseBytes > maxJvmMemory) {
            System.out.println("调整内存占用：配置的内存超过JVM最大可用内存");
            memoryToUseBytes = (long) (maxJvmMemory * 0.9); // 使用JVM最大内存的90%
        }
    }

    /**
     * 计算要占用的资源
     */
    private static void calculateResourcesToUse() {
        // 确保至少占用1个CPU核心
        if (cpuCoresToUse < 1) {
            cpuCoresToUse = 1;
        }

        // 确保内存占用不小于100MB
        if (memoryToUseBytes < 100 * 1024 * 1024) {
            memoryToUseBytes = 100 * 1024 * 1024;
        }
    }

    /**
     * 分配指定大小的内存
     */
    private static void allocateMemory() {
        System.out.println("开始分配内存... 目标: " + formatMemory(memoryToUseBytes));

        try {
            // 为了避免一次性分配过大内存导致OOM，分块分配
            long blockSize = 100 * 1024 * 1024; // 100MB每块
            long blocks = memoryToUseBytes / blockSize;
            long remaining = memoryToUseBytes % blockSize;

            byte[][] memoryBlocks = new byte[(int) (blocks + (remaining > 0 ? 1 : 0))][];

            for (int i = 0; i < blocks; i++) {
                memoryBlocks[i] = new byte[(int) blockSize];
                // 填充数据，确保内存被实际分配
                for (int j = 0; j < blockSize; j += 4096) {
                    memoryBlocks[i][j] = (byte) (i % 256);
                }
                System.out.printf("已分配 %.2f%% 内存\n", (i * 100.0) / blocks);
            }

            // 分配剩余部分
            if (remaining > 0) {
                memoryBlocks[(int) blocks] = new byte[(int) remaining];
                for (int j = 0; j < remaining; j += 4096) {
                    memoryBlocks[(int) blocks][j] = (byte) (blocks % 256);
                }
            }

            System.out.println("内存分配完成，已占用约 " + formatMemory(memoryToUseBytes));

            // 保持引用，防止被GC回收
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                // 释放内存引用
                for (int i = 0; i < memoryBlocks.length; i++) {
                    memoryBlocks[i] = null;
                }
            }));
        } catch (OutOfMemoryError e) {
            System.err.println("内存分配失败! 请检查JVM内存设置，确保-Xmx参数足够大");
            e.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * 创建指定数量的线程来占用CPU
     */
    private static void createCpuThreads() {
        System.out.println("开始创建CPU占用线程... 目标: " + cpuCoresToUse + " 个线程");

        cpuTasks = new CpuIntensiveTask[cpuCoresToUse];

        for (int i = 0; i < cpuCoresToUse; i++) {
            cpuTasks[i] = new CpuIntensiveTask(running);
            Thread thread = new Thread(cpuTasks[i], "CPU-Thread-" + (i + 1));
            thread.setPriority(Thread.NORM_PRIORITY);
            thread.start();
            System.out.println("已启动CPU占用线程: " + thread.getName());
        }
    }

    /**
     * 主线程保持运行
     */
    private static void keepRunning() {
        System.out.println("程序开始长时间运行，按Ctrl+C停止...");
        try {
            // 定期打印状态
            while (running) {
                Thread.sleep(60000); // 每分钟
                long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
                System.out.println("程序运行中... 内存使用: " + formatMemory(usedMemory) +
                        " / " + formatMemory(memoryToUseBytes));
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    /**
     * 格式化内存大小显示
     */
    private static String formatMemory(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.2f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.2f MB", bytes / (1024.0 * 1024));
        } else {
            return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
        }
    }
}
